package com.cyh.aidlservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

public class BookManagerService extends Service {
    private static final String TAG = "BMS";
    //并发读写，自动线程同步
    //ConcurrentHashMap
    private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();
    private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);
    //用下面这个解注册无法成功
    //private CopyOnWriteArrayList<IOnNewBookArrivedListener> mListenerList = new CopyOnWriteArrayList<>();
    //能自动线程同步，进程关闭是能自动解注册
    private RemoteCallbackList<IOnNewBookArrivedListener> mListenerList = new RemoteCallbackList<>();
    private Binder mBinder = new IBookManager.Stub() {
        /* 第二种权限验证
        @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
            int check=checkCallingPermission("com.csda.aidl.service.ACCESS_BOOK_SERVICE");
            if (check== PackageManager.PERMISSION_DENIED){
                return false;
            }
            return super.onTransact(code, data, reply, flags);
        }*/


       /* 权限验证
       @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
            String packageName = null;
            int callingPid = getCallingPid();
            int callingUid = getCallingUid();
            Log.i(TAG, "callingPid = " + callingPid + ",callingUid = " + callingUid);
            String[] packagesForUid = BookService.this.getPackageManager().getPackagesForUid(callingUid);
            if (packagesForUid != null && packagesForUid.length > 0) {
                packageName = packagesForUid[0];
            }
            Log.i(TAG, "packageName = " + packageName);
            if (TextUtils.isEmpty(packageName) || !"com.csda.aidl.client".equals(packageName)) {
                return false;
            }
            return super.onTransact(code, data, reply, flags);
        }*/

        @Override
        public List<Book> getBookList() throws RemoteException {
            Log.i(TAG, "Stub: getBookList");
            return mBookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            Log.i(TAG, "Stub: addBook");
            //如果有很多操作，需要synchronized 同步
            mBookList.add(book);
        }

        @Override
        public void notifyBook() throws RemoteException {
            Log.i(TAG, "Stub: notifyBook threaName = " + Thread.currentThread().getName());
            /**/
        }

        @Override
        public void registerListener(IOnNewBookArrivedListener listener) throws RemoteException {
            mListenerList.register(listener);
            /*if(!mListenerList.contains(listener)) {
                mListenerList.add(listener);
            } else {
                Log.i(TAG, "already exists");
            }*/
            final int N = mListenerList.beginBroadcast();
            Log.i(TAG, "registerListener, size:" + mListenerList.getRegisteredCallbackCount());
            mListenerList.finishBroadcast();
        }

        @Override
        public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException {
            mListenerList.unregister(listener);
            /*if(mListenerList.contains(listener)) {
                mListenerList.remove(listener);
                Log.i(TAG, "unregister listener succeed");
            } else {
                Log.i(TAG, "not found, can not unrigister");
            }*/
            final int N = mListenerList.beginBroadcast();
            Log.i(TAG, "unregisterListener, current size:" + mListenerList.getRegisteredCallbackCount());
            mListenerList.finishBroadcast();
        }
    };
    public BookManagerService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "service: onCreate");
        mBookList.add(new Book(1, "android"));
        mBookList.add(new Book(2, "ios"));
        new Thread(new ServiceWorker()).start();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "service: onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        mIsServiceDestoryed.set(true);
        super.onDestroy();
        Log.i(TAG, "service: onDestroy");
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG, "service: onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
        Log.i(TAG, "service: onRebind");
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG, "service: onBind");
        //这个地方可以加权限验证，不通过可以返回null
        /*<permission android:name="com.csda.aidl.service.ACCESS_BOOK_SERVICE"
        android:protectionLevel="normal"/>*/
        /*int check=checkCallingPermission("com.csda.aidl.service.ACCESS_BOOK_SERVICE");
        if (check== PackageManager.PERMISSION_DENIED){
            return null;
        }*/
        return mBinder;
    }

    private void onNewBookArrived(Book book) throws RemoteException{
        mBookList.add(book);
        Log.i(TAG, "onNewBookArrived, notify listeners size:" + mListenerList.getRegisteredCallbackCount());
        final int N = mListenerList.beginBroadcast();
        for(int i = 0; i < N; i++) {
            IOnNewBookArrivedListener listener = mListenerList.getBroadcastItem(i);
            Log.i(TAG, "onNewBookArrived, notify listener:" + listener);
            if(listener != null) {
                try {
                    //如果客户端很耗时，要在子线程中调用
                    listener.onNewBookArrived(book);
                }catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
        mListenerList.finishBroadcast();
    }

    private class ServiceWorker implements Runnable{
        @Override
        public void run() {
            while (!mIsServiceDestoryed.get()) {
                try{
                    Thread.sleep(5000);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
                int bookId = mBookList.size() + 1;
                Book newBook = new Book(bookId, "new book#" + bookId);
                try {
                    onNewBookArrived(newBook);
                }catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
